En la primera entrega vimos como usar la ayuda de IPython y como personalizar nuestras propias funciones mágicas de ayuda.
En esta segunda entrega vamos a hablar del uso de la historia dentro de IPython.
IPython guarda la historia de los comandos que se usan en cada línea/celda de cada sesión bajo un determinado perfil. Esta información se guarda en una base de datos sqlite. Por defecto, se guardan el inicio y fin de sesión, los comandos usados en cada sesión y algunos metadatos más. IPython también se puede configurar para que almacene los outputs.
La base de datos con la historia se guarda en la carpeta que obtenéis haciendo lo siguiente:
In [1]:
from IPython.utils import path
path.locate_profile()
Out[1]:
Y la base de datos se guardará en esa carpeta con el nombre history.sqlite.
Una forma alternativa de obtener la ruta a la historia bajo el perfil actual es usando lo siguiente:
In [2]:
get_ipython().history_manager.hist_file
Out[2]:
Para reusar comandos ya usados podemos hacer uso de la historia
que guarda IPython en cada sesión.
Podemos usar las teclas de cursor hacia arriba o hacia abajo para recorrer los últimos comandos usados (esto no funciona en el notebook pero sí en la consola de IPython).
Si escribimos algo en la línea de comandos y pulsamos el cursor hacia arriba nos mostrará solo lo que comience por lo ya escrito en la línea de comandos (nuevamente, esto no funciona en el notebook pero sí en la consola de IPython).
En las sesiones interactivas, el input y el output se guarda en las variables In y Out. Poniendo el índice de la línea usada nos volverá a ejecutar esa línea, en el caso de que usemos la variable In o nos mostrará el output en caso de que usemos la variable Out. In es una lista mientras que Out es un diccionario. En el caso de que no haya output para un número de línea nos dará un KeyError. Por ejemplo, veamos las siguientes celdas de código:
In [3]:
In?
Nos mostrará en pantalla lo siguiente:
Type: list
String Form:['', 'a = 3', 'a = 1', "get_ipython().magic('pinfo In')", "get_ipython().magic('pinfo In')"]
Length: 5
Docstring:
list() -> new empty list
list(iterable) -> new list initialized from iterable's items
Mientras que si hacemos lo mismo para Out
obtendremos la siguiente info:
Type: dict
String Form:{}
Length: 0
Docstring:
dict() -> new empty dictionary
dict(mapping) -> new dictionary initialized from a mapping object's
(key, value) pairs
dict(iterable) -> new dictionary initialized as if via:
d = {}
for k, v in iterable:
d[k] = v
dict(**kwargs) -> new dictionary initialized with the name=value pairs
in the keyword argument list. For example: dict(one=1, two=2)
Si ahora hacemos lo siguiente:
In [4]:
a = 2
In [5]:
print(a)
In [6]:
Out
Out[6]:
Vemos que en Out
se encuentra lo que hemos obtenido en las primeras celdas de código. Si ahora queremos ver otro output podemos hacer lo siguiente:
In [7]:
a
Out[7]:
In [8]:
Out
Out[8]:
Vemos que ya tenemos algún valor para el Out
y ya podremos acceder a ese valor por si lo quisiéramos usar en alguna otra celda. Por ejemplo, de la siguiente forma:
In [9]:
b = Out[7]
In [10]:
print(b)
Como el In
siempre lo tendremos, en lugar de ser un diccionario es una lista y podemos acceder al valor de la celda usando el índice de la misma. Por ejemplo:
In [11]:
for celda in In:
print(celda)
También podemos acceder a los tres últimos outputs de las tres últimas celdas usando _, __, ___, que nos mostrará el output de la última, penúltima o antepenúltima celdas usadas, respectivamente.
In [12]:
print('antepenúltima:\n', ___, '\n\n')
print('penúltima:\n', __, '\n\n')
print('última:\n', _, '\n\n')
Si queremos acceder a los inputs de las últimas celdas podemos usar algo parecido pero de la siguiente forma, _i, _ii o _iii para la última, penúltima o antepenúltima celda de input:
In [13]:
print('antepenúltima:\n', _iii, '\n\n')
print('penúltima:\n', _ii, '\n\n')
print('última:\n', _i, '\n\n')
Análogamente a lo visto anteriormente, podemos usar _n o _in para mostrar, respectivamente, el output o el input de la celda n. Por ejemplo, para ver el input y el output de la celda anterior (en este caso sería la 11) podemos hacer lo siguiente:
In [14]:
print('El input de la celda 11 es:')
print(_i11)
In [15]:
print('Te he engañado. No existe output para la celda 11')
print('Si intentas acceder al valor _11 obtendrás un NameError ya que no existe la variable')
print('pero te puedo enseñar el de la celda 7:')
print(_7)
Lo anterior es equivalente a usar In[n]
o Out[n]
. Una tercera alternativa, además, sería usar _ih[n] para los inputs y _oh[n] para los outputs.
In [16]:
In[11]
Out[16]:
In [17]:
_ih[11]
Out[17]:
Para acceder a toda la historia de la sesión actual podemos usar las funciones mágicas %history
o %hist
, que es un alias.
Podemos obtener toda la historia o solo una porción. Por ejemplo, el siguiente comando nos mostrará la historia desde la celda 1 a la 10 en la sesión actual:
In [18]:
%hist 1-10
Si, además de acceder a las celdas 1 a 10, queremos acceder a celdas sueltas podemos usar la siguiente notación para acceder a las celdas 12 y 14 (además de a las 10 primeras).
In [19]:
%hist 1-10 12 14
Si ahora queremos acceder a todas las celdas donde hayamos usado, por ejemplo, un comando que incluya 'a = 1
' podemos hacer uso de la opción -g
(similar a grep
) de la siguiente forma:
In [20]:
%hist -g a = 1
Pero esta busqueda no se restringe a la historia de la sesión actual sino que buscará en toda la historia almacenada por IPython bajo el perfil que estemos usando. El anterior output indica la sesión, el número de línea/celda de esa sesión y el código usado en esa línea/celda:
Sesión/celda: Código_introducido_en_la_celda
En este caso, podéis ver que en la última línea no se indica el número de sesión puesto que se refiere a la sesión actual:
Si usamos la opción -o
también obtendremos la historia con el output incluido. Podéis ver el siguiente ejemplo para ver como funciona:
In [21]:
%hist -o
Otra cosa interesante es la opción -p
, que coloca un prompt delante de cada línea de la historia que se muestra. Esto puede ser útil para, por ejemplo, escribir doctests.
En el siguiente ejemplo vamos a usar la opción -p
junto con la opción -o
:
In [22]:
%hist -po 1-10
Si queremos guardar la historia o parte de la historia en un fichero para, por ejemplo, los doctests, podemos usar la opción -f
.
Con la siguiente línea de código vamos a guardar el input, el output y vamos a colocar la línea del prompt de las 10 primeras celdas en un fichero llamado kk.txt:
In [23]:
%hist 1-10 -pof kk.txt
Si queremos acceder a la historia de una sesión anterior podemos usar lo siguiente:
In [24]:
%hist ~1/1-10
De esta forma accederemos a las 10 primeras líneas de la sesión anterior. Si queremos acceder a las 10 primeras líneas de la penúltima sesión podemos hacer:
In [25]:
%hist ~2/1-10
Si, además, queréis numerar las celdas usadas podéis usar la opción -n
:
In [26]:
%hist ~2/1-10 -n
Algunos de los comandos usados no son aceptados por un intérprete Python cualquiera, como por ejemplo los comandos mágicos que empiezan por %
. Por ello, podemos obtener los comandos ya traducidos a código Python ejecutable usando la opción -t
de la historia:
In [27]:
%hist 1-10 -t
En la tercera línea podéis ver que en lugar de escribir %pinfo In
ha escrito get_ipython().magic('pinfo In')
.
_dh
(también podemos usar %dhist
) nos da información de los directorios recorridos. Por ejemplo, voy a recorrer varios directorios y después veremos la historia de los directorios recorridos:
In [28]:
cd /home/kiko/pyprojs
In [29]:
pwd
Out[29]:
In [30]:
cd /home/kiko/pyprojs/ipython-master/nb/
In [31]:
%dhist
In [32]:
_dh
Out[32]:
Si solo quiero saber el directorio del que partí en la sesión de IPython en la que me encuentro puedo hacer lo siguiente:
In [33]:
_dh[0]
Out[33]:
Y esto es todo de momento. Podéis combinar muchas cosas de las vistas aquí con cosas como %macro
, %edit
, %pastebin
,... Si da tiempo, algo muy caro últimamente, hablaremos sobre algunas cosas que se me ocurren en próximas entregas.
Saludos y hasta la próxima entrega.
In [ ]: